#include "bsp_motor_def.h"
#include "bsp_motor_stm32f103.h"
#include "stm32f1xx_ll_bus.h"
#include "stm32f1xx_ll_tim.h"
#include "stm32f1xx_ll_gpio.h"

/**
 * 得科电机驱动板
 * IN1 低电平; IN2 PWM : 正向调速
 * IN1 PWM; IN2 低电平 : 反向调速
 * IN1和IN2同时低, 刹车
*/

/* TIM1 init function */
static void MX_TIM1_Init(void)
{
    LL_TIM_InitTypeDef TIM_InitStruct = {0};
    LL_TIM_OC_InitTypeDef TIM_OC_InitStruct = {0};
    LL_TIM_BDTR_InitTypeDef TIM_BDTRInitStruct = {0};

    LL_GPIO_InitTypeDef GPIO_InitStruct = {0};
    /* Peripheral clock enable */
    LL_APB2_GRP1_EnableClock(LL_APB2_GRP1_PERIPH_TIM1);

    TIM_InitStruct.Prescaler = 71;
    TIM_InitStruct.CounterMode = LL_TIM_COUNTERMODE_UP;
    TIM_InitStruct.Autoreload = 99;
    TIM_InitStruct.ClockDivision = LL_TIM_CLOCKDIVISION_DIV1;
    TIM_InitStruct.RepetitionCounter = 0;
    LL_TIM_Init(TIM1, &TIM_InitStruct);
    LL_TIM_EnableARRPreload(TIM1);
    LL_TIM_SetClockSource(TIM1, LL_TIM_CLOCKSOURCE_INTERNAL);
    LL_TIM_OC_EnablePreload(TIM1, LL_TIM_CHANNEL_CH1);
    TIM_OC_InitStruct.OCMode = LL_TIM_OCMODE_PWM1;
    TIM_OC_InitStruct.OCState = LL_TIM_OCSTATE_DISABLE;
    TIM_OC_InitStruct.OCNState = LL_TIM_OCSTATE_DISABLE;
    TIM_OC_InitStruct.CompareValue = 0;
    TIM_OC_InitStruct.OCPolarity = LL_TIM_OCPOLARITY_HIGH;
    TIM_OC_InitStruct.OCNPolarity = LL_TIM_OCPOLARITY_HIGH;
    TIM_OC_InitStruct.OCIdleState = LL_TIM_OCIDLESTATE_LOW;
    TIM_OC_InitStruct.OCNIdleState = LL_TIM_OCIDLESTATE_LOW;
    LL_TIM_OC_Init(TIM1, LL_TIM_CHANNEL_CH1, &TIM_OC_InitStruct);
    LL_TIM_OC_DisableFast(TIM1, LL_TIM_CHANNEL_CH1);
    LL_TIM_OC_EnablePreload(TIM1, LL_TIM_CHANNEL_CH2);
    LL_TIM_OC_Init(TIM1, LL_TIM_CHANNEL_CH2, &TIM_OC_InitStruct);
    LL_TIM_OC_DisableFast(TIM1, LL_TIM_CHANNEL_CH2);
    LL_TIM_OC_EnablePreload(TIM1, LL_TIM_CHANNEL_CH3);
    LL_TIM_OC_Init(TIM1, LL_TIM_CHANNEL_CH3, &TIM_OC_InitStruct);
    LL_TIM_OC_DisableFast(TIM1, LL_TIM_CHANNEL_CH3);
    LL_TIM_OC_EnablePreload(TIM1, LL_TIM_CHANNEL_CH4);
    LL_TIM_OC_Init(TIM1, LL_TIM_CHANNEL_CH4, &TIM_OC_InitStruct);
    LL_TIM_OC_DisableFast(TIM1, LL_TIM_CHANNEL_CH4);
    LL_TIM_SetTriggerOutput(TIM1, LL_TIM_TRGO_RESET);
    LL_TIM_DisableMasterSlaveMode(TIM1);
    TIM_BDTRInitStruct.OSSRState = LL_TIM_OSSR_DISABLE;
    TIM_BDTRInitStruct.OSSIState = LL_TIM_OSSI_DISABLE;
    TIM_BDTRInitStruct.LockLevel = LL_TIM_LOCKLEVEL_OFF;
    TIM_BDTRInitStruct.DeadTime = 0;
    TIM_BDTRInitStruct.BreakState = LL_TIM_BREAK_DISABLE;
    TIM_BDTRInitStruct.BreakPolarity = LL_TIM_BREAK_POLARITY_HIGH;
    TIM_BDTRInitStruct.AutomaticOutput = LL_TIM_AUTOMATICOUTPUT_DISABLE;
    LL_TIM_BDTR_Init(TIM1, &TIM_BDTRInitStruct);

    /**TIM1 GPIO Configuration
    PE9     ------> TIM1_CH1
    PE11     ------> TIM1_CH2
    PE13     ------> TIM1_CH3
    PE14     ------> TIM1_CH4
    */
    GPIO_InitStruct.Pin = LL_GPIO_PIN_9|LL_GPIO_PIN_11|LL_GPIO_PIN_13|LL_GPIO_PIN_14;
    GPIO_InitStruct.Mode = LL_GPIO_MODE_OUTPUT;
    GPIO_InitStruct.Speed = LL_GPIO_SPEED_FREQ_MEDIUM;
    GPIO_InitStruct.OutputType = LL_GPIO_OUTPUT_PUSHPULL;
    LL_GPIO_Init(GPIOE, &GPIO_InitStruct);
    LL_GPIO_ResetOutputPin(GPIOE, LL_GPIO_PIN_9|LL_GPIO_PIN_11|LL_GPIO_PIN_13|LL_GPIO_PIN_14);

    LL_GPIO_AF_EnableRemap_TIM1();

    /// 驱动添加部分
    LL_TIM_EnableCounter(TIM1);
    LL_TIM_EnableAllOutputs(TIM1);
}

/* TIM3 init function */
static void MX_TIM3_Init(void)
{
    LL_TIM_InitTypeDef TIM_InitStruct = {0};
    LL_TIM_OC_InitTypeDef TIM_OC_InitStruct = {0};

    LL_GPIO_InitTypeDef GPIO_InitStruct = {0};
    /* Peripheral clock enable */
    LL_APB1_GRP1_EnableClock(LL_APB1_GRP1_PERIPH_TIM3);

    TIM_InitStruct.Prescaler = 35;
    TIM_InitStruct.CounterMode = LL_TIM_COUNTERMODE_UP;
    TIM_InitStruct.Autoreload = 99;
    TIM_InitStruct.ClockDivision = LL_TIM_CLOCKDIVISION_DIV1;
    LL_TIM_Init(TIM3, &TIM_InitStruct);
    LL_TIM_EnableARRPreload(TIM3);
    LL_TIM_SetClockSource(TIM3, LL_TIM_CLOCKSOURCE_INTERNAL);
    LL_TIM_OC_EnablePreload(TIM3, LL_TIM_CHANNEL_CH1);
    TIM_OC_InitStruct.OCMode = LL_TIM_OCMODE_PWM1;
    TIM_OC_InitStruct.OCState = LL_TIM_OCSTATE_DISABLE;
    TIM_OC_InitStruct.OCNState = LL_TIM_OCSTATE_DISABLE;
    TIM_OC_InitStruct.CompareValue = 0;
    TIM_OC_InitStruct.OCPolarity = LL_TIM_OCPOLARITY_HIGH;
    LL_TIM_OC_Init(TIM3, LL_TIM_CHANNEL_CH1, &TIM_OC_InitStruct);
    LL_TIM_OC_DisableFast(TIM3, LL_TIM_CHANNEL_CH1);
    LL_TIM_OC_EnablePreload(TIM3, LL_TIM_CHANNEL_CH2);
    LL_TIM_OC_Init(TIM3, LL_TIM_CHANNEL_CH2, &TIM_OC_InitStruct);
    LL_TIM_OC_DisableFast(TIM3, LL_TIM_CHANNEL_CH2);
    LL_TIM_OC_EnablePreload(TIM3, LL_TIM_CHANNEL_CH3);
    LL_TIM_OC_Init(TIM3, LL_TIM_CHANNEL_CH3, &TIM_OC_InitStruct);
    LL_TIM_OC_DisableFast(TIM3, LL_TIM_CHANNEL_CH3);
    LL_TIM_OC_EnablePreload(TIM3, LL_TIM_CHANNEL_CH4);
    LL_TIM_OC_Init(TIM3, LL_TIM_CHANNEL_CH4, &TIM_OC_InitStruct);
    LL_TIM_OC_DisableFast(TIM3, LL_TIM_CHANNEL_CH4);
    LL_TIM_SetTriggerOutput(TIM3, LL_TIM_TRGO_RESET);
    LL_TIM_DisableMasterSlaveMode(TIM3);

    /**TIM3 GPIO Configuration
    PC6     ------> TIM3_CH1
    PC7     ------> TIM3_CH2
    PC8     ------> TIM3_CH3
    PC9     ------> TIM3_CH4
    */
    GPIO_InitStruct.Pin = LL_GPIO_PIN_6|LL_GPIO_PIN_7|LL_GPIO_PIN_8|LL_GPIO_PIN_9;
    GPIO_InitStruct.Mode = LL_GPIO_MODE_OUTPUT;
    GPIO_InitStruct.Speed = LL_GPIO_SPEED_FREQ_MEDIUM;
    GPIO_InitStruct.OutputType = LL_GPIO_OUTPUT_PUSHPULL;
    LL_GPIO_Init(GPIOC, &GPIO_InitStruct);
    LL_GPIO_ResetOutputPin(GPIOC, LL_GPIO_PIN_6|LL_GPIO_PIN_7|LL_GPIO_PIN_8|LL_GPIO_PIN_9);

    LL_GPIO_AF_EnableRemap_TIM3();

    /// 驱动添加部分
    LL_TIM_EnableCounter(TIM3);
    LL_TIM_EnableAllOutputs(TIM3);
}

void Drv_MotorOpen(void)
{
    MX_TIM1_Init();
    MX_TIM3_Init();
}

void Drv_MotorClose(void)
{
    LL_GPIO_SetPinMode(GPIOE, LL_GPIO_PIN_9|LL_GPIO_PIN_11|LL_GPIO_PIN_13|LL_GPIO_PIN_14, LL_GPIO_MODE_OUTPUT);
    LL_GPIO_ResetOutputPin(GPIOE, LL_GPIO_PIN_9|LL_GPIO_PIN_11|LL_GPIO_PIN_13|LL_GPIO_PIN_14);

    LL_GPIO_SetPinMode(GPIOC, LL_GPIO_PIN_6|LL_GPIO_PIN_7|LL_GPIO_PIN_8|LL_GPIO_PIN_9, LL_GPIO_MODE_OUTPUT);
    LL_GPIO_ResetOutputPin(GPIOC, LL_GPIO_PIN_6|LL_GPIO_PIN_7|LL_GPIO_PIN_8|LL_GPIO_PIN_9);

    LL_TIM_DeInit(TIM1);
    LL_TIM_DeInit(TIM2);

    LL_APB2_GRP1_DisableClock(LL_APB2_GRP1_PERIPH_TIM1);
    LL_APB1_GRP1_EnableClock(LL_APB1_GRP1_PERIPH_TIM3);
}

void Drv_MotorSetDirection(Bsp_TMotorItem* item)
{
    switch (item->id)
    {
    case Bsp_kMotorIdFrontLeft:
        {   /// IN1: PE9, IN2: PE11
            if (item->direction)
            {
                LL_GPIO_ResetOutputPin(GPIOE, LL_GPIO_PIN_9);
                LL_GPIO_SetPinMode(GPIOE, LL_GPIO_PIN_9, LL_GPIO_MODE_OUTPUT);

                LL_GPIO_SetPinMode(GPIOE, LL_GPIO_PIN_11, LL_GPIO_MODE_ALTERNATE);
            }
            else
            {
                LL_GPIO_ResetOutputPin(GPIOE, LL_GPIO_PIN_11);
                LL_GPIO_SetPinMode(GPIOE, LL_GPIO_PIN_11, LL_GPIO_MODE_OUTPUT);

                LL_GPIO_SetPinMode(GPIOE, LL_GPIO_PIN_9, LL_GPIO_MODE_ALTERNATE);
            }
        }
        break;
    case Bsp_kMotorIdFrontRight:
        {   /// IN1: PE13, IN2: PE14
            if (item->direction)
            {
                LL_GPIO_ResetOutputPin(GPIOE, LL_GPIO_PIN_13);
                LL_GPIO_SetPinMode(GPIOE, LL_GPIO_PIN_13, LL_GPIO_MODE_OUTPUT);

                LL_GPIO_SetPinMode(GPIOE, LL_GPIO_PIN_14, LL_GPIO_MODE_ALTERNATE);
            }
            else
            {
                LL_GPIO_ResetOutputPin(GPIOE, LL_GPIO_PIN_14);
                LL_GPIO_SetPinMode(GPIOE, LL_GPIO_PIN_14, LL_GPIO_MODE_OUTPUT);

                LL_GPIO_SetPinMode(GPIOE, LL_GPIO_PIN_13, LL_GPIO_MODE_ALTERNATE);
            }
        }
        break;
    case Bsp_kMotorIdRearLeft:
        {   /// IN1: PC6, IN2: PC7
            if (item->direction)
            {
                LL_GPIO_ResetOutputPin(GPIOC, LL_GPIO_PIN_6);
                LL_GPIO_SetPinMode(GPIOC, LL_GPIO_PIN_6, LL_GPIO_MODE_OUTPUT);

                LL_GPIO_SetPinMode(GPIOC, LL_GPIO_PIN_7, LL_GPIO_MODE_ALTERNATE);
            }
            else
            {
                LL_GPIO_ResetOutputPin(GPIOC, LL_GPIO_PIN_7);
                LL_GPIO_SetPinMode(GPIOC, LL_GPIO_PIN_7, LL_GPIO_MODE_OUTPUT);

                LL_GPIO_SetPinMode(GPIOC, LL_GPIO_PIN_6, LL_GPIO_MODE_ALTERNATE);
            }
        }
        break;
    case Bsp_kMotorIdRearRight:
        {   /// IN1: PC8, IN2: PC9
            if (item->direction)
            {
                LL_GPIO_ResetOutputPin(GPIOC, LL_GPIO_PIN_8);
                LL_GPIO_SetPinMode(GPIOC, LL_GPIO_PIN_8, LL_GPIO_MODE_OUTPUT);

                LL_GPIO_SetPinMode(GPIOC, LL_GPIO_PIN_9, LL_GPIO_MODE_ALTERNATE);
            }
            else
            {
                LL_GPIO_ResetOutputPin(GPIOC, LL_GPIO_PIN_9);
                LL_GPIO_SetPinMode(GPIOC, LL_GPIO_PIN_9, LL_GPIO_MODE_OUTPUT);

                LL_GPIO_SetPinMode(GPIOC, LL_GPIO_PIN_8, LL_GPIO_MODE_ALTERNATE);
            }
        }
        break;
    default:
        break;
    }
}

void Drv_MotorSetDuty(Bsp_TMotorItem* item)
{
    switch (item->id)
    {
    case Bsp_kMotorIdFrontLeft:
        {
            LL_TIM_OC_SetCompareCH1(TIM1, item->duty);
            LL_TIM_OC_SetCompareCH2(TIM1, item->duty);
        }
        break;
    case Bsp_kMotorIdFrontRight:
        {
            LL_TIM_OC_SetCompareCH3(TIM1, item->duty);
            LL_TIM_OC_SetCompareCH4(TIM1, item->duty);
        }
        break;
    case Bsp_kMotorIdRearLeft:
        {
            LL_TIM_OC_SetCompareCH1(TIM3, item->duty);
            LL_TIM_OC_SetCompareCH2(TIM3, item->duty);
        }
        break;
    case Bsp_kMotorIdRearRight:
        {
            LL_TIM_OC_SetCompareCH3(TIM3, item->duty);
            LL_TIM_OC_SetCompareCH4(TIM3, item->duty);
        }
        break;
    default:
        break;
    }
}

void Drv_MotorStart(Bsp_TMotorItem* item)
{
    switch (item->id)
    {
    case Bsp_kMotorIdFrontLeft:
        {
            LL_TIM_CC_EnableChannel(TIM1, LL_TIM_CHANNEL_CH1);
            LL_TIM_CC_EnableChannel(TIM1, LL_TIM_CHANNEL_CH2);
            
            // LL_TIM_GenerateEvent_UPDATE(TIM1);
            // LL_TIM_GenerateEvent_CC1(TIM1);
            // LL_TIM_GenerateEvent_CC2(TIM1);
        }
        break;
    case Bsp_kMotorIdFrontRight:
        {
            LL_TIM_CC_EnableChannel(TIM1, LL_TIM_CHANNEL_CH3);
            LL_TIM_CC_EnableChannel(TIM1, LL_TIM_CHANNEL_CH4);
        }
        break;
    case Bsp_kMotorIdRearLeft:
        {
            LL_TIM_CC_EnableChannel(TIM3, LL_TIM_CHANNEL_CH1);
            LL_TIM_CC_EnableChannel(TIM3, LL_TIM_CHANNEL_CH2);
        }
        break;
    case Bsp_kMotorIdRearRight:
        {
            LL_TIM_CC_EnableChannel(TIM3, LL_TIM_CHANNEL_CH3);
            LL_TIM_CC_EnableChannel(TIM3, LL_TIM_CHANNEL_CH4);
        }
        break;
    default:
        break;
    }
}

void Drv_MotorStop(Bsp_TMotorItem* item)
{
    switch (item->id)
    {
    case Bsp_kMotorIdFrontLeft:
        {
            LL_TIM_CC_DisableChannel(TIM1, LL_TIM_CHANNEL_CH1);
            LL_TIM_CC_DisableChannel(TIM1, LL_TIM_CHANNEL_CH2);
        }
        break;
    case Bsp_kMotorIdFrontRight:
        {
            LL_TIM_CC_DisableChannel(TIM1, LL_TIM_CHANNEL_CH3);
            LL_TIM_CC_DisableChannel(TIM1, LL_TIM_CHANNEL_CH4);
        }
        break;
    case Bsp_kMotorIdRearLeft:
        {
            LL_TIM_CC_DisableChannel(TIM3, LL_TIM_CHANNEL_CH1);
            LL_TIM_CC_DisableChannel(TIM3, LL_TIM_CHANNEL_CH2);
        }
        break;
    case Bsp_kMotorIdRearRight:
        {
            LL_TIM_CC_DisableChannel(TIM3, LL_TIM_CHANNEL_CH3);
            LL_TIM_CC_DisableChannel(TIM3, LL_TIM_CHANNEL_CH4);
        }
        break;
    default:
        break;
    }
}
